<template>
  <div class="app-container">
    <!-- 查询和其他操作 -->
    <div class="filter-container">
      <el-input
        v-model="listQuery.name"
        clearable
        class="filter-item"
        style="width: 200px;"
        placeholder="请输入角色名称"
      />
      <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
        查找
      </el-button>
      <el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">
        添加
      </el-button>
    </div>

    <!-- 查询结果 -->
    <el-table
      v-loading="listLoading"
      :data="tableData.data"
      size="small"
      element-loading-text="正在查询中。。。"
      border
      fit
      highlight-current-row
    >
      <el-table-column align="center" label="角色ID" prop="role_id" sortable />
      <el-table-column align="center" label="角色名称" prop="role_name" />
      <el-table-column align="center" label="角色描述" prop="role_desc" />
      <!-- 操作按钮组件 -->
      <action-button
        :handle-update="handleUpdate"
        :handle-delete="handleDelete"
        :loading="deleteLoading"
        update-auth="Role::update"
        delete-auth="Role::delete"
        :disable-update="(item) => item.role_id === 1"
        :disable-delete="(item) => item.role_id === 1"
      />
    </el-table>

    <!-- 添加或修改对话框 -->
    <dialog-form
      ref="dataForm"
      :status="dialogStatus"
      :rules="rules"
      :data="dataForm"
      :loading="dialogFormLoading"
      @createData="createData"
      @updateData="updateData"
      width="500px"
    >
      <template>
        <el-form-item label="角色名称" prop="role_name">
          <el-input v-model="dataForm.role_name" />
        </el-form-item>
        <el-form-item label="角色描述" prop="role_desc">
          <el-input v-model="dataForm.role_desc" />
        </el-form-item>
        <el-form-item label="关联菜单" prop="menu">
          <el-tree
            :data="menuList"
            show-checkbox
            node-key="id"
            ref="tree"
            :default-checked-keys="menus"
            :props="{ children: 'children', label: 'title' }"
          ></el-tree>
        </el-form-item>
      </template>
    </dialog-form>
  </div>
</template>

<script>
import table from '@/mixins/table'
import { listRole, createRole, updateRole, deleteRole } from '@/api/role'
import { getMenu } from '@/api/menu'
import { deepClone } from '@/utils'

export default {
  name: 'Role',
  mixins: [table],
  data() {
    return {
      pageTitle: '角色',
      getListApi: listRole,
      createApi: createRole,
      updateApi: updateRole,
      deleteApi: deleteRole,
      rules: {
        role_name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
        role_desc: [{ required: true, message: '角色描述不能为空', trigger: 'blur' }]
      },
      menuList: [],
      handleMenus: [],
      menus: []
    }
  },
  created() {
    this.getMenu()
  },
  methods: {
    resetForm() {
      this.dataForm = {
        role_id: undefined,
        role_name: undefined,
        role_desc: undefined
      }
      this.setTree([])
    },
    setTableData(data) {
      // TODO abstract table数据初始化，可以被覆盖，但大部分情况你不应该覆盖它
      this.tableData = {
        total: data.length,
        data: data.map((item) => {
          item.deleteVisible = false
          return item
        }),
        finished: true
      }
    },
    setTree(keys) {
      if (this.$refs.tree) {
        this.$refs.tree.setCheckedKeys(keys)
        for (var i = 0; i < this.$refs.tree.store._getAllNodes().length; i++) {
          this.$refs.tree.store._getAllNodes()[i].expanded = false
        }
      }
    },
    setDataForm(data) {
      // TODO abstract 编辑时设置表单内容，需要被重写
      this.dataForm = { ...data }
      const menus = data.menu_ids.filter((e) => {
        return data.half_menu_ids.indexOf(e) === -1
      })
      this.$nextTick(() => {
        this.setTree([
          ...menus.map((menu_id) => `menu:${menu_id}`),
          ...data.api_ids.map((api_id) => `api:${api_id}`)
        ])
      })
    },
    getSubmitData() {
      const halfMenuIds = this.$refs.tree.getHalfCheckedKeys()
      const menuIds = this.$refs.tree.getCheckedKeys().concat(halfMenuIds)
      return {
        ...this.dataForm,
        menu_ids: menuIds
          .filter((item) => item.indexOf('menu:') > -1)
          .map((item) => item.replace('menu:', ''))
          .join(','),
        api_ids: menuIds
          .filter((item) => item.indexOf('api:') > -1)
          .map((item) => item.replace('api:', ''))
          .join(','),
        half_menu_ids: halfMenuIds
          .filter((item) => item.indexOf('menu:') > -1)
          .map((item) => item.replace('menu:', ''))
          .join(',')
      }
    },
    async getMenu() {
      this.listLoading = true
      const { err, res } = await getMenu('')
      if (err === null) {
        let data = res
        this.resetForm()
        this.menuList = data.map((menu) => {
          return {
            id: `menu:${menu.menu_id}`,
            title: `menu:${menu.title}`,
            children: [
              ...menu.children.map((child) => {
                return {
                  id: `menu:${child.menu_id}`,
                  title: `menu:${child.title}`,
                  children: child.api.map((api) => {
                    return {
                      id: `api:${api.api_id}`,
                      title: `api:${api.api_name}`
                    }
                  })
                }
              }),
              ...menu.api.map((api) => {
                return {
                  id: `api:${api.api_id}`,
                  title: `api:${api.api_name}`
                }
              })
            ]
          }
        })
      }
      this.listLoading = false
    }
  }
}
</script>
<style>
.el-tag + .el-tag {
  margin-left: 10px;
}
.checkbox-group {
  margin-top: 10px;
  margin-left: 20px;
}
</style>
